﻿/*
 * Created by SharpDevelop.
 * User: Alice
 * Date: 03.03.2012
 * Time: 21:34
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using MySql.Data;
using MySql.Data.MySqlClient;
using System.Collections;

namespace monoServer
{
	/// <summary>
	/// Description of DataBase.
	/// </summary>
	public class DataBase
	{
		private String _server;
		public String Server
		{
			get
			{
				return this._server;
			}
			set
			{
				this._server = value;
			}
		}
		
		private User _user;
		public User DataBaseUser
		{
			get
			{
				return this._user;
			}
			set
			{
				this._user = value;
			}
		}
		
		private String _name;
		public String DataBaseName
		{
			get
			{
				return this._name;
			}
			set
			{
				this._name = value;
			}
		}
		
		public Logger logger;
		
		public DataBase(Logger l, User u, String addr, String name, int num)
		{
			this.logger = l;
			this.DataBaseUser = u;
			this.Server = addr;
			this.DataBaseName = name;
			this.initPool(num);
		}
		
		private Queue _connectionPool;
		private MySql.Data.MySqlClient.MySqlConnection connection
		{
			// TODO Was passiert wenn keine Datenbankverbindungen im pool vorhanden sind und ein deenqueue wird aufgerufen? Es kracht!!!
			// Es muss überprüft werden ob noch verbindungen im pool sind. sind keine vorhanden muss der requester in eine art warteschlange
			// gestellt werden.
			get 
			{
				return (MySql.Data.MySqlClient.MySqlConnection) this._connectionPool.Dequeue();
			}
			set
			{
				this._connectionPool.Enqueue(value);
			}
				
		}
		
		private void initPool(int num)
		{
			this._connectionPool = new Queue();
			for(int i=0; i<= num-1; i++)
			{
				try {
					string constr = this.getConnectionString();
					MySql.Data.MySqlClient.MySqlConnection con = new MySql.Data.MySqlClient.MySqlConnection(constr);
					con.Open();
					this.connection = con;
				} catch (Exception ex) {
					throw new Exception("Initializing of DB-Pool error: #"+i.ToString()+" from DATABASE: "+ex.Message);
				}
			}
		}
		
		public void connect()
		{
			try
			{
				this.connection = new MySql.Data.MySqlClient.MySqlConnection(this.getConnectionString());
				this.connection.Open();
			}
			catch (MySql.Data.MySqlClient.MySqlException ex)
			{
				throw(ex);
			}
		}
		
		public String getConnectionString() {
			return "server=" + this.Server + ";uid=" + this.DataBaseUser.NickName + ";pwd=" + this.DataBaseUser.Password + ";database=" + this.DataBaseName;
		}
		
		public SortedList getChatMessages(int timestamp)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			SortedList sl = new SortedList();
			String sql = "select chat.id,timestamp,sessionkey,ip,player_id,players.nickname,message,channel from players, chat where players.id = chat.player_id and timestamp >= " + timestamp.ToString();
			MySqlCommand cmd = new MySqlCommand(sql, con);
			MySqlDataReader rdr = cmd.ExecuteReader();
			while(rdr.Read())
			{
				Hashtable h = new Hashtable();
				int t = (int)rdr["timestamp"];
				h["timestamp"] = t;
				h["ip"] = (String)rdr["ip"];
				h["sessionkey"] = (String)rdr["sessionkey"];
				h["message"] = (String)rdr["message"];
				h["player"] = new User((int)rdr["player_id"], (String)rdr["nickname"]);
				sl.Add(h["timestamp"],h);
			}
			
			this.connection = con;
			rdr.Close();
			return sl;
		}
	
		public void addChatMessage(Hashtable h)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			String sql = "insert into chat (timestamp,sessionkey,ip,player_id,message) values ("+h["timestamp"].ToString()+",'"+h["sessionkey"]+"','"+h["ip"].ToString()+"',"+((User)h["player"]).ID+",'"+h["message"]+"')";
			MySqlCommand cmd = new MySqlCommand(sql, con);
			cmd.ExecuteNonQuery();
			this.connection = con;
		}
		
		public User setUserWrongPassword(User u, int value1)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			String sql = "update players set count_wrong_password=" + value1.ToString() + " where id = " + u.ID.ToString();
			u.countWrongPassword++;
			MySqlCommand cmd = new MySqlCommand(sql, con);
			cmd.ExecuteNonQuery();
			this.connection = con;
			return u;
		}
		
		public User setUserBannToTime(User u, long time)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			String sql = "update players set banned_until = " + time.ToString() + " where id = " + u.ID.ToString();
			u.bannedUntil = time;
			MySqlCommand cmd = new MySqlCommand(sql, con);
			cmd.ExecuteNonQuery();
			this.connection = con;
			return u;
		}
		
		public User getAdmin(String name, String pw)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			User u = null;
			String sql = "select id,name,password,level from admins where name = '"+name+"'";
			MySqlCommand cmd = new MySqlCommand(sql, con);
			MySqlDataReader rdr = cmd.ExecuteReader();
			rdr.Read();
			if(rdr.HasRows)
			{
				if(rdr[2].Equals(pw))
				{
					u = new User((int)rdr[0],(String)rdr[1],(int)rdr[3]);
					u.IsLoggedIn = true;					
				} else {
					u = new User();
					u.IsLoggedIn = false;
					u.e = new Error(1003);
				}
			} else
			{
				u = new User();
				u.e = new Error(1004);
			}
			
			rdr.Close();
			this.connection = con;
			return u;
		}
		
		public User getUser(String name, String pw, long timenow)
		{
			MySql.Data.MySqlClient.MySqlConnection con = this.connection;
			User tmpuser = new User();
			tmpuser.IsLoggedIn = false;
			String sql = "select id,nickname,password,banned_until,count_wrong_password,x,y from players where nickname = '"+name+"'";
			MySqlCommand cmd = new MySqlCommand(sql, con);
			MySqlDataReader rdr = cmd.ExecuteReader();
			rdr.Read();
			if(rdr.HasRows)
			{
				if(rdr[2].Equals(pw) && (long)rdr[3] < DateTime.Now.Ticks)
				{
					// Passwort ist richtig!
					//this.logger.log(this.logger.BOTH, this.logger.ERROR, "Client " + name + " eingeloggt!");
					tmpuser.ID = (int)rdr[0];
					tmpuser.NickName = name;
					tmpuser.Password = pw;
					tmpuser.bannedUntil = (long)rdr[3];
					tmpuser.countWrongPassword = (int)rdr[4];
					tmpuser.xPosition = (int)rdr[5];
					tmpuser.yPosition = (int)rdr[6];
					tmpuser.IsLoggedIn = true;
					
				} else
				{
					if((long)rdr[3] > timenow)
						tmpuser.e = new Error(1005);
					else
						tmpuser.e = new Error(1003);
				}
			} else
			{
				// Benutzer existiert nicht
				tmpuser.e = new Error(1004);
			}
			rdr.Close();
			this.connection = con;
			return tmpuser;
		}
	}
}
